package com.zxkj.ssm.weixin.shop.config.shiro;

import com.zxkj.ssm.weixin.shop.shiro.CluterShiroSessionDao;
import com.zxkj.ssm.weixin.shop.shiro.UserRealm;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * @Author 程序媛
 * @Date @2017年7月28日
 * @Description: 权限框架SHiro组件配置
 */

@Configuration
public class ShiroConfiguration implements EnvironmentAware {
    /**
     * 实现EnvironmentAware  注入env 环境 不然为null
     */
    private Environment env;

    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
    }


    @Bean
    public UserRealm userRealm() {
        UserRealm realm = new UserRealm();
        return realm;
    }

    @Bean
    public CluterShiroSessionDao cluterShiroSessionDao() {
        CluterShiroSessionDao cluterShiroSessionDao = new CluterShiroSessionDao();
        return cluterShiroSessionDao;
    }


    /**
     * 会话管理
     *
     * @return
     */
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(CluterShiroSessionDao cluterShiroSessionDao) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(Long.parseLong(
                env.getProperty("shiro.globalSessionTimeout")));
        sessionManager.setDeleteInvalidSessions(Boolean.parseBoolean(
                env.getProperty("shiro.deleteInvalidSessions")));
        sessionManager.setSessionValidationSchedulerEnabled(//
                Boolean.parseBoolean(env.getProperty("shiro.sessionValidationSchedulerEnabled")));
        sessionManager.setSessionDAO(cluterShiroSessionDao);
        return sessionManager;

    }

    /**
     * 安全认证管理器
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(DefaultWebSessionManager defaultWebSessionManager, UserRealm authenticationRealm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(authenticationRealm);
        defaultWebSecurityManager.setSessionManager(defaultWebSessionManager);
        return defaultWebSecurityManager;
    }


    /**
     * Shiro生命周期处理器
     * 用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调
     *
     * @return
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 决定对哪些类的方法进行AOP代理。
     */
    @Bean
    @ConditionalOnMissingBean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    /**
     * AuthorizationAttributeSourceAdvisor，shiro里实现的Advisor类，
     * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法(如@RequiresRoles，@RequiresPermissions)，。
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(defaultWebSecurityManager);
        return advisor;
    }

    /**
     * Shiro 主过滤器
     *
     * @return
     * @throws Exception
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) throws Exception {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //System.out.println(env.getProperty("shiro.login.url"));
        shiroFilterFactoryBean.setLoginUrl(env.getProperty("shiro.login.url"));
        shiroFilterFactoryBean.setSuccessUrl(env.getProperty("shiro.success.url"));
        shiroFilterFactoryBean.setUnauthorizedUrl(env.getProperty("shiro.unauthorized.url"));
        ClassPathResource resource = new ClassPathResource(env.getProperty("shiro.filter.link"));
        try (InputStream is = resource.getInputStream()) {
            List<String> urls = IOUtils.readLines(is, "UTF-8");
            shiroFilterFactoryBean.setFilterChainDefinitions(StringUtils.join(urls, "\r\n"));
        }
     /*   try {
            shiroFilterFactoryBean.setFilterChainDefinitions(
                    FileUtils.readFileToString(new DefaultResourceLoader().getResource(env.getProperty("shiro.filter.link")).getFile(), "UTF-8"));

            //FileUtils.in
         String filter=   FileUtils.readFileToString(new DefaultResourceLoader().getResource(env.getProperty("shiro.filter.link")).getFile());

            System.out.println("load filer successfully"+filter);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        return shiroFilterFactoryBean;
    }


}
